﻿using NPOI.SS.UserModel;
using System.Text;

namespace Yz.Core.Tools.Excel
{
    public class HtmlHelper
    {
        private static readonly List<KeyValuePair<HorizontalAlignment, string>> HALIGN = new List<KeyValuePair<HorizontalAlignment, string>>
    {
        new KeyValuePair<HorizontalAlignment, string>( HorizontalAlignment.Left, "left"),
        new KeyValuePair<HorizontalAlignment, string>( HorizontalAlignment.Center, "center"),
        new KeyValuePair<HorizontalAlignment, string>(HorizontalAlignment.Right, "right"),
        new KeyValuePair<HorizontalAlignment, string>( HorizontalAlignment.Fill, "left"),
        new KeyValuePair<HorizontalAlignment, string>( HorizontalAlignment.Justify, "left"),
        new KeyValuePair<HorizontalAlignment, string>( HorizontalAlignment.CenterSelection, "center")
    };

        private static readonly List<KeyValuePair<VerticalAlignment, string>> VALIGN = new List<KeyValuePair<VerticalAlignment, string>>
    {
        new KeyValuePair<VerticalAlignment, string>( VerticalAlignment.Bottom, "bottom"),
        new KeyValuePair<VerticalAlignment, string>(VerticalAlignment.Center, "middle"),
        new KeyValuePair<VerticalAlignment, string>( VerticalAlignment.Top, "top")
    };

        private static readonly List<KeyValuePair<BorderStyle, string>> BORDER = new List<KeyValuePair<BorderStyle, string>>
    {
        new KeyValuePair<BorderStyle, string>( BorderStyle.DashDot, "dashed 1pt"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.DashDotDot, "dashed 1pt"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.Dashed, "dashed 1pt"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.Dotted, "dotted 1pt"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.Double, "double 3pt"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.Hair, "dashed 1px"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.Medium, "solid 2pt"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.MediumDashDot, "dashed 2pt"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.MediumDashDotDot, "dashed 2pt"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.MediumDashed, "dashed 2pt"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.None, "none"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.SlantedDashDot, "dashed 2pt"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.Thick, "solid 3pt"),
        new KeyValuePair<BorderStyle, string>( BorderStyle.Thin, "solid 1pt")
    };

        public static string GetExcelHtml(IEnumerable<ExcelSheetModel> sheetList)
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();

            StringBuilder strb = new StringBuilder();

            AddStrToHtml("<!DOCTYPE html>", ref strb);

            AddStrToHtml("<html lang=\"zh-CN\">", ref strb);

            AddStrToHtml("<head>", ref strb);

            AddStrToHtml("    <meta name=\"renderer\" content=\"webkit|ie-comp|ie-stand\" />", ref strb);

            AddStrToHtml("    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />", ref strb);

            AddStrToHtml("    <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">", ref strb);

            AddStrToHtml("    <meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1,IE=edge\">", ref strb);

            AddStrToHtml("    <title>EXCEl预览</title>", ref strb);

            AddStrToHtml("    <style>", ref strb);

            AddStrToHtml("        html,body,.sheet-content{", ref strb);

            AddStrToHtml("            position: relative;", ref strb);

            AddStrToHtml("            height: 100%;", ref strb);

            AddStrToHtml("            width: 100%;", ref strb);

            AddStrToHtml("            -moz-box-sizing: border-box;", ref strb);

            AddStrToHtml("            -webkit-box-sizing: border-box;", ref strb);

            AddStrToHtml("            box-sizing: border-box;", ref strb);

            AddStrToHtml("            margin: 0;", ref strb);

            AddStrToHtml("            padding: 0;", ref strb);

            AddStrToHtml("            overflow: hidden;", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("        .sheet-bar{", ref strb);

            AddStrToHtml("            -moz-box-sizing: border-box;", ref strb);

            AddStrToHtml("            -webkit-box-sizing: border-box;", ref strb);

            AddStrToHtml("            box-sizing: border-box;", ref strb);

            AddStrToHtml("            position:absolute;", ref strb);

            AddStrToHtml("            bottom: 0;", ref strb);

            AddStrToHtml("            left: 0;", ref strb);

            AddStrToHtml("            border-top: 1px solid #ccc;", ref strb);

            AddStrToHtml("            height: 32px;", ref strb);

            AddStrToHtml("            width: 100%;", ref strb);

            AddStrToHtml("            font-size: 0;", ref strb);

            AddStrToHtml("            white-space:nowrap;", ref strb);

            AddStrToHtml("            overflow-x: auto;", ref strb);

            AddStrToHtml("            overflow-y: hidden;", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("        .sheet-bar-item{", ref strb);

            AddStrToHtml("            -moz-box-sizing: border-box;", ref strb);

            AddStrToHtml("            -webkit-box-sizing: border-box;", ref strb);

            AddStrToHtml("            box-sizing: border-box;", ref strb);

            AddStrToHtml("            position: relative;", ref strb);

            AddStrToHtml("            display: inline-block;", ref strb);

            AddStrToHtml("            font-size: 14px;", ref strb);

            AddStrToHtml("            height: 32px;", ref strb);

            AddStrToHtml("            line-height: 32px;", ref strb);

            AddStrToHtml("            padding: 0 16px;", ref strb);

            AddStrToHtml("            border-right:1px solid #ccc;", ref strb);

            AddStrToHtml("            background-color: #f2f2f2;", ref strb);

            AddStrToHtml("            cursor: pointer;", ref strb);

            AddStrToHtml("            color: #666;", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("        .sheet-bar-item.active{", ref strb);

            AddStrToHtml("            background-color: #fff;", ref strb);

            AddStrToHtml("            color: #04BCC1;", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("        .sheet-bar-item.active:after {", ref strb);

            AddStrToHtml("            position: absolute;", ref strb);

            AddStrToHtml("            left: 0;", ref strb);

            AddStrToHtml("            bottom: 0;", ref strb);

            AddStrToHtml("            content: '';", ref strb);

            AddStrToHtml("            width: 100%;", ref strb);

            AddStrToHtml("            height: 4px;", ref strb);

            AddStrToHtml("            box-sizing: border-box;", ref strb);

            AddStrToHtml("            pointer-events: none;", ref strb);

            AddStrToHtml("            border-bottom: 4px solid #04BCC1;", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("        .sheet-content-item{", ref strb);

            AddStrToHtml("            position: relative;", ref strb);

            AddStrToHtml("            height: 100%;", ref strb);

            AddStrToHtml("            width: 100%;", ref strb);

            AddStrToHtml("            -moz-box-sizing: border-box;", ref strb);

            AddStrToHtml("            -webkit-box-sizing: border-box;", ref strb);

            AddStrToHtml("            box-sizing: border-box;", ref strb);

            AddStrToHtml("            overflow: auto;", ref strb);

            AddStrToHtml("            display: none;", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("        .sheet-content-item.show{", ref strb);

            AddStrToHtml("            display: block;", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("        td{", ref strb);

            AddStrToHtml("            height: 13.5pt;", ref strb);

            AddStrToHtml("            font-size: 11pt;", ref strb);

            AddStrToHtml("            white-space: pre;", ref strb);

            AddStrToHtml("            color:#000;", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("        .ftr>td{", ref strb);

            AddStrToHtml("            height: 0;", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("        .right{", ref strb);

            AddStrToHtml("            text-align: right;", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("        .center{", ref strb);

            AddStrToHtml("            text-align: center;", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("{$style}", ref strb);

            AddStrToHtml("    </style>", ref strb);

            AddStrToHtml("</head>", ref strb);

            AddStrToHtml("<body style=\"padding-bottom: 32px;\" >", ref strb);

            AddStrToHtml("    <div class=\"sheet-content\" >", ref strb);
            string text = "";
            int num = 0;
            foreach (ExcelSheetModel sheet in sheetList)
            {
                text += "<div class=\"sheet-bar-item";
                if (num == 0)
                {
                    text += " active ";
                }
                text = text + "\" data-value=\"" + sheet.Id + "\"  >" + sheet.Name + "</div>";

                AddStrToHtml("        <div class=\"sheet-content-item " + ((num == 0) ? "show" : "") + " \" id =\"" + sheet.Id + "\" >" + GetSheetHtml(sheet, dictionary) + "</div>", ref strb);
                num++;
            }

            AddStrToHtml("    </div>", ref strb);

            AddStrToHtml("    <div class=\"sheet-bar\" >", ref strb);

            AddStrToHtml("        " + text, ref strb);

            AddStrToHtml("    </div>", ref strb);

            AddStrToHtml("    <script>", ref strb);

            AddStrToHtml("        window.onload = function(){", ref strb);

            AddStrToHtml("            var btnlist = document.querySelectorAll('.sheet-bar-item');", ref strb);

            AddStrToHtml("            for(var i = 0,l =btnlist.length;i<l;i++){", ref strb);

            AddStrToHtml("                btnlist[i].onclick=function () {", ref strb);

            AddStrToHtml("                    var sheetId = this.getAttribute('data-value');", ref strb);

            AddStrToHtml("                    if(this.className.indexOf('active') == -1){", ref strb);

            AddStrToHtml("                        document.getElementsByClassName('active')[0].className = 'sheet-bar-item';", ref strb);

            AddStrToHtml("                        this.className = 'sheet-bar-item active';", ref strb);

            AddStrToHtml("                        document.getElementsByClassName('show')[0].className = 'sheet-content-item';", ref strb);

            AddStrToHtml("                        document.getElementById(sheetId).className = 'sheet-content-item show';", ref strb);

            AddStrToHtml("                    }", ref strb);

            AddStrToHtml("                }", ref strb);

            AddStrToHtml("            }", ref strb);

            AddStrToHtml("        }", ref strb);

            AddStrToHtml("    </script>", ref strb);

            AddStrToHtml("</body>", ref strb);

            AddStrToHtml("</html>", ref strb);
            string text2 = "";
            foreach (KeyValuePair<string, string> item in dictionary)
            {
                text2 = text2 + "        ." + item.Value + "{" + item.Key + "}\r\n";
            }
            string text3 = strb.ToString();
            return text3.Replace("{$style}", text2);
        }
        private static void AddStrToHtml(string str, ref StringBuilder strb)
        {
            strb.Append(str + "\r\n");
        }

        public static string GetSheetHtml(ExcelSheetModel sheet, Dictionary<string, string> classMap)
        {

            StringBuilder strb = new StringBuilder();

            AddStrToHtml("<table cellspacing=\"0\" cellpadding=\"0\" style=\"border-collapse:collapse;table-layout:fixed;width:" + sheet.TableWidth.ToString() + "px;\"  >", ref strb);

            AddStrToHtml("<tr class=\"ftr\">", ref strb);
            foreach (decimal cellWidth in sheet.CellWidths)
            {

                AddStrToHtml("<td style=\"" + GetPXStyle("width", cellWidth) + "\"></td>", ref strb);
            }

            AddStrToHtml("</tr>", ref strb);
            foreach (ExcelRowModel row in sheet.Rows)
            {

                AddStrToHtml("<tr>", ref strb);
                foreach (ExcelCellModel cell in row.Cells)
                {
                    string style = GetStyle(cell);
                    string text = "";
                    if (!string.IsNullOrEmpty(style))
                    {
                        string text2 = "c" + classMap.Count.ToString();
                        if (classMap.ContainsKey(style))
                        {
                            text2 = classMap[style];
                        }
                        else
                        {
                            classMap.Add(style, text2);
                        }
                        text = "class=\"" + text2 + "\"";
                    }

                    AddStrToHtml(string.Format("<td {0}{1}{2}>{3}</td>", text, GetRowColSpan("rowspan", cell.RowSpan), GetRowColSpan("colspan", cell.ColumnSpan), cell.Text), ref strb);
                }

                AddStrToHtml("</tr>", ref strb);
            }

            AddStrToHtml("</table>", ref strb);
            return strb.ToString();
        }

        private static string GetPXStyle(string k, decimal w)
        {
            return k + ":" + w.ToString() + "px;";
        }
        private static string GetRowColSpan(string type, int span)
        {
            if (span == 1)
            {
                return "";
            }
            return $" {type}=\"{span}\"";
        }


        private static string GetStyle(ExcelCellModel cell)
        {
            string str = "";
            str += StyleOut("text-align", cell.Alignment, cell.CellType);
            str += StyleOut("vertical-align", cell.VerticalAlignment);
            str += StyleOut("border-left", cell.BorderLeft, cell.BorderLeftColor);
            str += StyleOut("border-right", cell.BorderRight, cell.BorderRightColor);
            str += StyleOut("border-top", cell.BorderTop, cell.BorderTopColor);
            str += StyleOut("border-bottom", cell.BorderBottom, cell.BorderBottomColor);
            str += StyleOut(cell.WrapText);
            str += SetHeight(cell.HeightInPoints);
            if (cell.Font != null)
            {
                str += SetFontWeight(cell.Font.IsBold);
                str += SetFontSize(cell.Font.FontHeightInPoints);
                str += SetFontItalic(cell.Font.IsItalic);
                str += SetFontFamily(cell.Font.FontName);
            }
            str += SetFillColor(cell.FillColor);
            return str + SetFontColor(cell.FontColor);
        }
        private static string StyleOut(string k, HorizontalAlignment p, CellType cellType)
        {

            if ((int)p == 0)
            {
                return ((int)cellType == 0) ? "text-align:right;" : (((int)cellType - 4 > 1) ? "" : "text-align:center;");
            }
            return k + ":" + (from o in HALIGN
                              where o.Key == p
                              select o).First().Value + ";";
        }

        private static string StyleOut(string k, VerticalAlignment p)
        {
            return k + ":" + (from o in VALIGN
                              where o.Key == p
                              select o).First().Value + ";";
        }

        private static string StyleOut(string k, BorderStyle p, string color)
        {
            if ((int)p == 0)
            {
                return "";
            }
            string str = k + ":" + (from o in BORDER
                                    where o.Key == p
                                    select o).First().Value;
            if (!string.IsNullOrEmpty(color))
            {
                str = str + " " + color;
            }
            return str + ";";
        }

        private static string StyleOut(bool isWrapText)
        {
            if (isWrapText)
            {
                return "white-space:pre-wrap;";
            }
            return "";
        }
        private static string SetHeight(float h)
        {
            if (h == 0f)
            {
                return "";
            }
            return "height:" + h.ToString() + "pt;";
        }
        private static string SetFontWeight(bool isBold)
        {
            if (isBold)
            {
                return "font-weight:bold;";
            }
            return "";
            //if (w == 400)
            //{
            //    return "";
            //}
            //return "font-weight:" + w.ToString() + ";";
        }

        private static string SetFontSize(double size)
        {
            if (size == 11.0)
            {
                return "";
            }
            return "font-size:" + size.ToString() + "pt;";
        }

        private static string SetFontItalic(bool isItalic)
        {
            if (isItalic)
            {
                return "font-style:italic;";
            }
            return "";
        }

        private static string SetFontFamily(string FontName)
        {
            if (!string.IsNullOrEmpty(FontName))
            {
                return "font-family:" + FontName + ";";
            }
            return "";
        }

        private static string SetFillColor(string color)
        {
            if (!string.IsNullOrEmpty(color))
            {
                return "background-color:" + color + ";";
            }
            return "";
        }

        private static string SetFontColor(string color)
        {
            if (string.IsNullOrEmpty(color) || color == "#000000")
            {
                return "";
            }
            return "color:" + color + ";";
        }
    }
}
